Динамические стратегии
Вы, вероятно, уже использовали один из шаблонов стратегии - поведенческий шаблон, который позволяет выбирать алгоритм во время выполнения.
Итак, вот такие входные данные у нас есть:
[
'{"title":"test"}',
'<title>test</title>',
['title' => 'test']
]
Которые будут сконвертированы в json
{
"title": "test"
}
О, есть еще одно требование: нам нужно, чтобы эти стратегии были расширяемыми. Разработчикам должно быть позволено добавлять свои собственные стратегии для работы с другими типами входных данных: YAML, интерфейсами, итерируемыми объектами и всем, что им нужно.
Давайте взглянем на классическое решение и его проблемы.
Обычно мы начинаем с введения какого-то интерфейса, который должны реализовывать все стратегии:
interface ParserInterface
{
public function canParse(mixed $input): bool;
public function parse(mixed $input): mixed;
}
Каждая стратегия должна определять, может ли она работать на заданных входных данных, и обеспечивать фактическую реализацию.
Далее мы можем предоставить несколько реализаций этого интерфейса:
final class ArrayParser implements ParserInterface
{
public function canParse(mixed $input): bool
{
return is_array($input);
}
public function parse(mixed $input): mixed
{
return json_encode($input, JSON_PRETTY_PRINT);
}
}
final class JsonParser implements ParserInterface
{
public function canParse(mixed $input): bool
{
return
is_string($input)
&& str_starts_with(trim($input), '{')
&& str_ends_with(trim($input), '}');
}
public function parse(mixed $input): mixed
{
return json_encode(
json_decode($input),
JSON_PRETTY_PRINT
);
}
}
final class XmlParser implements ParserInterface
{
public function canParse(mixed $input): bool
{
return
is_string($input)
&& str_starts_with(trim($input), '<')
&& str_ends_with(trim($input), '>');
}
public function parse(mixed $input): mixed
{
return json_encode(
simplexml_load_string(
$input,
"SimpleXMLElement",
LIBXML_NOCDATA
),
JSON_PRETTY_PRINT
);
}
}